package com.wbihua.metrics.manager;

import com.wbihua.common.metrics.config.MeterConfig;
import com.wbihua.common.metrics.manager.MetricManager;
import com.wbihua.common.metrics.metric.*;
import com.wbihua.common.metrics.type.*;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class PrometheusMetricManager implements MetricManager {

    private final MeterConfig config;
    private PrometheusMeterRegistry meterRegistry;
    private final ConcurrentMap<EventCounterType, EventMeterCounter> metricCounterMap = new ConcurrentHashMap<>();
    private final ConcurrentMap<EventGaugeType, EventMeterGauge> metricGaugeMap = new ConcurrentHashMap<>();
    private final ConcurrentMap<EventPrometheusSummaryType, EventMeterPrometheusSummary> prometheusSummaryMap = new ConcurrentHashMap<>();
    private final ConcurrentMap<EventPrometheusHistogramType, EventMeterPrometheusHistogram> prometheusHistogramMap = new ConcurrentHashMap<>();
    private final ConcurrentMap<EventTimerType, EventMeterTimer> timerMap = new ConcurrentHashMap<>();
    private final ConcurrentMap<EventSummaryType, EventMeterSummary> summaryMap = new ConcurrentHashMap<>();

    public PrometheusMetricManager(MeterConfig config) {
        this.config = config;
        this.meterRegistry = Optional.ofNullable(meterRegistry).orElse(new PrometheusMeterRegistry(PrometheusConfig.DEFAULT));
        Metrics.globalRegistry.config().commonTags(getTags());
        Metrics.globalRegistry.add( this.meterRegistry);
    }
    public PrometheusMetricManager(MeterConfig config, PrometheusMeterRegistry meterRegistry) {
        this.config = config;
        this.meterRegistry =meterRegistry;
        Metrics.globalRegistry.config().commonTags(getTags());
        Metrics.globalRegistry.add( this.meterRegistry);
    }

    @Override
    public MeterConfig getMeterConfig() {
        return this.config;
    }

    @Override
    public MeterRegistry getMetricRegistry() {
        return this.meterRegistry;
    }

    @Override
    public void registryEventMeterCounter(EventMeterCounter counter) {
        counter.registry(this);
        metricCounterMap.put(counter.getCounterType(), counter);
    }

    @Override
    public EventMeterCounter getEventMeterCounter(EventCounterType counterType) {
        return this.metricCounterMap.get(counterType);
    }

    @Override
    public void registryEventMeterGauge(EventMeterGauge gauge) {
        gauge.registry(this);
        metricGaugeMap.put(gauge.getCounterType(), gauge);
    }

    @Override
    public EventMeterGauge getEventMeterGauge(EventGaugeType gaugeType) {
        return this.metricGaugeMap.get(gaugeType);
    }


    @Override
    public void registryEventMeterTimer(EventMeterTimer timer) {
        timer.registry(this);
        timerMap.put(timer.getCounterType(), timer);

    }

    @Override
    public EventMeterTimer getEventMeterTimer(EventTimerType timerType) {
        return timerMap.get(timerType);
    }

    @Override
    public void registryEventMeterSummary(EventMeterSummary summary) {
        summary.registry(this);
        summaryMap.put(summary.getCounterType(), summary);
    }

    @Override
    public EventMeterSummary getEventMeterSummary(EventSummaryType summaryType) {
        return summaryMap.get(summaryType);
    }

    @Override
    public void registryEventMeterPrometheusSummary(EventMeterPrometheusSummary prometheusSummary) {
        prometheusSummary.registry(this);
        prometheusSummaryMap.put(prometheusSummary.getCounterType(), prometheusSummary);
    }

    @Override
    public EventMeterPrometheusSummary getEventMeterPrometheusSummary(EventPrometheusSummaryType summaryType) {
        return this.prometheusSummaryMap.get(summaryType);
    }

    @Override
    public void registryEventMeterPrometheusHistogram(EventMeterPrometheusHistogram prometheusHistogram) {
        prometheusHistogram.registry(this);
        prometheusHistogramMap.put(prometheusHistogram.getCounterType(), prometheusHistogram);
    }

    @Override
    public EventMeterPrometheusHistogram getEventMeterPrometheusHistogram(EventPrometheusHistogramType histogramType) {
        return prometheusHistogramMap.get(histogramType);
    }
}
